/**
 * 文件名：@AbstractFeatureHandlerMapping.java <br/>
 * 包名：cn.efunbox.afw.web.mvc.springmvc <br/>
 * 项目名：afw-web <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.web.mvc.springmvc;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;

/**
 * 类名：AbstractFeatureHandlerMapping  <br />
 *
 * 功能：使用接口特征进行映射
 *
 * @author xtwin <br />
 * 创建时间：2016年7月20日 下午5:05:54  <br />
 * @version 2016年7月20日
 */
public abstract class AbstractFeatureHandlerMapping extends AbstractHandlerMethodMapping<Set<String>> {
	
	// 特征请求头
	private String headerName = "Feature";
	
	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月20日 下午5:11:14<br/>
	 * 
	 * @param method
	 * @param handlerType
	 * @return <br/>
	 * @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getMappingForMethod(java.lang.reflect.Method, java.lang.Class)
	 */
	@Override
	protected Set<String> getMappingForMethod(Method method, Class<?> handlerType) {
		Set<String> mappings = getMappingForMethod(method, handlerType, handlerType.getInterfaces());
		
		return null == mappings || mappings.isEmpty() ? null : mappings;
	}
	
	/**
	 * 功能： <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月21日 上午9:54:59 <br/>
	 */
	protected Set<String> getMappingForMethod(Method method, Class<?> handlerType, Class<?>[] interfaces) {
		// 映射容器
		Set<String> mappings = new HashSet<>();
		
		// 方法参数列表
		Class<?>[] ptypes = method.getParameterTypes();
		// 方法名
		String name = method.getName();
		for (Class<?> inf : interfaces) {
			do {
				for (Method _method : inf.getDeclaredMethods()) {
					if (name.equals(_method.getName()) 
							&& Arrays.equals(ptypes, _method.getParameterTypes())
							/*&& method.getReturnType().isAssignableFrom(_method.getReturnType())*/) {
						
						// 组装接口特征
						String signature = new StringBuilder()
								.append(inf.getName()).append(":")
								.append(method.getName()).append(":")
								.append(Arrays.toString(method.getParameterTypes()))
								//.append(_method.getReturnType().getName())
							.toString();
						
						//signature = postMapping(signature, _method, handlerType, inf);
						
						// 添加到映射关系
						mappings.add(toFeature(signature, _method, handlerType, inf));
					}
				}
				
				// 取得父级接口
				inf = inf.getSuperclass();
			} while (null != inf);
		}
		
		return mappings;
	}
	
	/**
	 * 功能：转为特征码 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月21日 上午10:01:30 <br/>
	 */
	protected String toFeature(String mapping, Method method, Class<?> handlerType, Class<?> inf) {
		return Base64Utils.encodeToUrlSafeString(DigestUtils.md5Digest(mapping.getBytes()));
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月20日 下午5:11:14<br/>
	 * 
	 * @param mapping
	 * @return <br/>
	 * @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getMappingPathPatterns(java.lang.Object)
	 */
	@Override
	protected Set<String> getMappingPathPatterns(Set<String> mapping) {
		return mapping;
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月20日 下午5:11:14<br/>
	 * 
	 * @param mapping
	 * @param request
	 * @return <br/>
	 * @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getMatchingMapping(java.lang.Object, javax.servlet.http.HttpServletRequest)
	 */
	@Override
	protected Set<String> getMatchingMapping(Set<String> mapping, HttpServletRequest request) {
		// 取出特征码
		String feature = request.getHeader(headerName);
		if (StringUtils.isEmpty(feature)) {
			feature = request.getRequestURI();
			int index = feature.lastIndexOf('/');
			if (index != -1) {
				feature = feature.substring(index + 1);
			}
			
			index = feature.lastIndexOf('.');
			if (index != -1) {
				feature = feature.substring(0, index);
			}
		}
		
		return mapping.contains(feature) ? mapping : null;
	}

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月20日 下午5:11:14<br/>
	 * 
	 * @param request
	 * @return <br/>
	 * @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getMappingComparator(javax.servlet.http.HttpServletRequest)
	 */
	@Override
	protected Comparator<Set<String>> getMappingComparator(HttpServletRequest request) {
		return new Comparator<Set<String>>() {
			@Override
			public int compare(Set<String> left, Set<String> right) {
				return left.toString().compareTo(right.toString());
			}
		};
	}

	/**
	 * @version 2016年7月20日-下午5:48:54
	 */
	public String getHeaderName() {
		return headerName;
	}

	/**
	 * @version 2016年7月20日-下午5:48:54
	 */
	public void setHeaderName(String headerName) {
		this.headerName = headerName;
	}
}
